package edu.scsu.csci;

import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;

import edu.scsu.csci.interceptor.EInterceptorFlow;
import edu.scsu.csci.interceptor.IInterceptorChain;
import edu.scsu.csci.interceptor.InterceptorChain;
import edu.scsu.csci.interceptor.NullInterceptor;
import edu.scsu.csci.util.ReflectionUtil;


/**
 *
 * <p>	Should be implemented by all the defined interceptors.
 * 
 * <p>	Interceptors as the name suggests provides a way to intercept 
 * 		the request and do things like auditing,etc. This promotes a
 * 		lossely coupled and cohesive design.
 * 
 * <p>	The interceptors could be added and removed without affecting the
 * 		buisness logic and vice versa.
 * 
 * @author Maqbool Khan
 * @since jdk 1.5
 * @see	edu.scsu.csci.annotation.AInterceptor
 * @see edu.scsu.csci.interceptor.EInterceptorFlow
 * @viz.diagram IInterceptor.tpx
 */
public interface IInterceptor<T> {
	
	/**
	 * <p> This would be called before the business logic for the request is invoked. </p>
	 * 
	 * @param operationContext
	 * @return
	 */
	EInterceptorFlow preProcess(T domainObject, ServletRequest request, ServletResponse response);
	
	
	/**
	 * <p> This would be called before the business logic for the request is invoked. </p>
	 * 
	 * @param opeartionContext
	 * @return
	 */
	EInterceptorFlow postProcess(T domainObject, ServletRequest request, ServletResponse response);
	
	
	/**
	 * <p>  A factory to create interceptors defined for the current request. </p>
	 *  
	 * <p>	It creats an interceptor based on the number interceptors that has been defined for the request
	 * 		<ul>
	 * 			<li> one interceptor - creates a simple interceptor </li>
	 * 			<li> no interceptor -  creates a null interceptor </li>
	 * 			<li> more than one -   creates an interceptor chain </li>
	 * 		</ul>
	 * </p>
	 *  
	 * @author Maqbool Khan
	 * @since jdk 1.5
	 * @see edu.scsu.csci.interceptor.IInterceptorChain
	 */
	final public static class InterceptorFactory {
		
		/**
		 * Implements the interface but provides no implementation. To get rid of the conditional logic.
		 */
		private static IInterceptor<Object> nullInterceptor = new NullInterceptor();
		
		/**
		 * <p> Creates an interceptor </p>
		 * 
		 * @param interceptors
		 * @return IInterceptor
		 */
		public static IInterceptor create(Class<? extends IInterceptor>[] interceptors)	{
			if(interceptors == null || interceptors.length <= 0)
				return nullInterceptor;
			
			if(interceptors.length == 1)	{
				return ReflectionUtil.instantiate(interceptors[0]);
			}
			
			//creates and returns a composite interceptor
			IInterceptorChain interceptorChain = new InterceptorChain();
			for(int i = 0, length = interceptors.length; i < length; i++)	{
				interceptorChain.addInterceptor(ReflectionUtil.instantiate(interceptors[i]));
			}
			return interceptorChain;
		}
	}

	
}
